/*
 * Description: process preload handler
 */
#ifndef PERF_PROCESS_PRELOAD_H_
#define PERF_PROCESS_PRELOAD_H_
#include <windows.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <functional>
#include "singleton.h"

namespace PERF {
void ProcessCheckNeedCloseTimerFunc();
void ProcessSuspendAndSetMemFunc();

class ProcessPreload {
public:
    ProcessPreload(){};
    bool ProcessPreloadEntry(std::string &appName, DWORD processId, std::string &cmdLine, std::string &appPath);
    bool IsTargetProcessExist(const std::string &name);
    void PreloadProcessHide(const std::string &name);
    DWORD GetProcessRunningDuration(DWORD processId);
    bool SetProcessWorkingSet(DWORD processId);
    void ClosePreloadProcess(DWORD processId);
    std::vector<DWORD> GetAllProcessIdByName(const std::string &name);
    bool SuspendOrResumeProcessByName(const std::string &process_name, DWORD processId, bool isNeedSuspend);
    void CloseAllPreloadProcess();

private:
    BOOL GetUserTokenByProcessName(HANDLE &hToken, const std::string &name);
    void GetTokenByProcessId(HANDLE &hToken, DWORD processId);
    bool ExecCmdWithWithoutTimeOutAsUser(const std::string &cmd, const std::string &processName,
        const std::string &appName, bool showBool);
    bool CreateProcessAsCurretUser(const std::string &cmd, const std::string &processName, STARTUPINFO &si,
        PROCESS_INFORMATION &pi, const std::string &appName);
    bool MemoryUsageLimitExceed();
    void KillPhotoShopResidue();
    BOOL KillPreloadProcess(DWORD processID);
    bool GetFilePath(std::string &filePathStr);
    void ProcessPsPreloadEntry(std::string &appName, DWORD processId, std::string &cmdLine);
    void ProcessAutoCadPreloadEntry(std::string &appName, DWORD processId, std::string &cmdLine, std::string &appPath);
    void ProcessXmindPreloadEntry(std::string &appName, DWORD processId, std::string &cmdLine, std::string &appPath);
    bool FindProcessPid(LPCSTR ProcessName, DWORD &dwPid);
    void PsPreloadTimerTask(std::function<void()> callback, int interval);
    void ProcessPsPreloadEntryTimerFunc(std::string &cmdLinePs);
    bool SuspendOrResumeThreadByTid(HANDLE hth, bool isNeedSuspend);
    std::string FilePathTranslation(std::string &filePathStr);
    bool ProcessAcadCheckAndDealPreload(std::string &appName, DWORD processId, std::string &cmdLine);
    bool ProcessAcadCheckAndDealFileOpen(
        std::string &appName, DWORD processId, std::string &cmdLine, std::string &appPath);
    bool ProcessAcadCheckAndDealAppStart(
        std::string &appName, DWORD processId, std::string &cmdLine, std::string &appPath);
    void SuspendOrResumeProcessByThread(DWORD processId, bool isNeedSuspend);
    void ProcessPreloadEntryTimerFunc();
    bool ProcessXmindCheckAndDealFileOpen(DWORD processId, std::string &cmdLine);
    bool ProcessXmindCheckAndDealPreload(std::string &cmdLine);
    bool ProcessXmindCheckAndDealAppStart(DWORD processId, std::string &appPath);
    void XmindPreloadTimerTask(std::function<void()> callback, int interval);
    void XmindPreloadSuspendTimerTask(std::function<void()> callback, int interval);
    void XmindFileCloseTimerTask(std::function<void()> callback, int interval);
    void XmindPreloadCheckIsNeedCloseTimerTask(std::function<void()> callback, int interval);
    void XmindProcessPreloadEntryTimerFunc();
    void XmindProcessSuspendAndSetMemFunc();
    void XmindProcessCloseTimerFunc();
    void XmindProcessCheckNeedCloseTimerFunc();
    void CloseAllXmindLoadProcess(std::vector<DWORD> &xmindProcessId);
    void ProcessSuspendAndSetMemByProcessId(std::string &processName, DWORD processId, bool isNeedSuspend);
    void OpenXmindFileWhenLessProcess(std::string &xmindFilePath, std::string &xmindProcessName);
    void OpenXmindFileByFilePath(std::string &xmindFilePath, std::string &xmindProcessName);
    void HandleXmindAppStart(DWORD processId, std::string &appPath);
    bool FilePathIsVaildCheck(std::string &filePath);
};
#define PERF_PROCESS_PRELOAD SingletonNew<PERF::ProcessPreload>::GetInstance()
}  // namespace PERF
#endif